﻿using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;

namespace AllServer.Core;

public static class IpHelper
{   

    /// <summary>
    /// IP地址转十进制整数
    /// </summary>
    /// <param name="ipAddress"></param>
    /// <returns></returns>
    /// <exception cref="ArgumentException"></exception>
    public static uint ConvertIpToInt(this string ipAddress)
    {
        uint result = 0;
        byte[] bytes = new byte[4];

        if (ipAddress.Split('.').Length != 4)
        {
            return 0;
            //throw new ArgumentException("Invalid IPv4 address.");
        }

        for (int i = 0; i < 4; i++)
        {
            if (!uint.TryParse(ipAddress.Split('.')[i], out uint temp) || temp > 255)
            {
                throw new ArgumentException("Invalid IPv4 address.");
            }

            bytes[i] = (byte)temp;
        }

        result += (uint)(bytes[0] << 24);
        result += (uint)(bytes[1] << 16);
        result += (uint)(bytes[2] << 8);
        result += bytes[3];

        return result;
    }

    /// <summary>
    /// 十进制整数转IP地址
    /// </summary>
    /// <param name="ipAddress"></param>
    /// <returns></returns>
    public static string ConvertIntToIp(this uint ipAddress)
    {
        byte[] bytes = BitConverter.GetBytes(ipAddress);
        if (BitConverter.IsLittleEndian)
        {
            Array.Reverse(bytes);
        }

        return bytes[0] + "." + bytes[1] + "." + bytes[2] + "." + bytes[3];
    }


    /// <summary>
    /// 获取客户Ip
    /// </summary>
    /// <returns></returns>
    public static string GetClientUserIp()
    {
        var ip = App.HttpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault();
        if (string.IsNullOrWhiteSpace(ip))
        {
            var ipAddress = App.HttpContext.Connection.RemoteIpAddress;
            if (ipAddress != null)
            {
                if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
                {
                    ip = ipAddress.MapToIPv4().ToString();
                }
                else if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    ip = ipAddress.MapToIPv6().ToString();
                }
            }

        }
        if (ip.IndexOf(',') != -1) //防止获取到多个IP，只取第一个真实ip
        {
            return ip.Split(',')[0].Trim();
        }
        return ip;
    }

    /// <summary>
    /// 获取真实IP
    /// </summary>
    /// <returns></returns>
    public static string GetClientIP()
    {
        string ip = "127.0.0.1";
        if (App.HttpContext.Request.Headers.ContainsKey("X-Real-IP"))
        {
            ip = App.HttpContext.Request.Headers["X-Real-IP"].ToString();
        }
        if (App.HttpContext.Request.Headers.ContainsKey("X-Forwarded-For"))
        {
            ip = App.HttpContext.Request.Headers["X-Forwarded-For"].ToString();
        }
        return ip;
    }

    public static string GetRealClientIpAddress()
    {
        string ip = null;
        // 尝试从 X-Forwarded-For 协议头中获取真实 IP 地址
        string xff = App.HttpContext.GetServerVariable("HTTP_X_FORWARDED_FOR");
        if (!string.IsNullOrEmpty(xff))
        {
            // 从逗号分隔列表中获取第一个不是私有地址和代理服务器地址的 IP 地址
            foreach (string address in xff.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                IPAddress parsedAddress;
                if (IPAddress.TryParse(address.Trim(), out parsedAddress) && !IsPrivateIpAddress(parsedAddress) && !IsProxyIpAddress(parsedAddress))
                {
                    ip = address.Trim();
                    break;
                }
            }
        }
        // 如果没有找到真实 IP 地址，则尝试从 RemoteAddr 属性中获取 IP 地址
        if (ip == null)
        {
            IPAddress remoteAddress;
            if (IPAddress.TryParse(App.HttpContext.GetServerVariable("REMOTE_ADDR"), out remoteAddress))
            {
                if (!IsPrivateIpAddress(remoteAddress) && !IsProxyIpAddress(remoteAddress))
                {
                    ip = remoteAddress.ToString();
                }
            }
        }

        return ip ?? string.Empty;
    }

    // 检查 IP 地址是否为私有地址
    private static bool IsPrivateIpAddress(IPAddress ipAddress)
    {
        byte[] addressBytes = ipAddress.GetAddressBytes();
        if (addressBytes[0] == 10 ||
            (addressBytes[0] == 172 && addressBytes[1] >= 16 && addressBytes[1] <= 31) ||
            (addressBytes[0] == 192 && addressBytes[1] == 168))
        {
            return true;
        }
        return false;
    }

    // 检查 IP 地址是否为代理服务器地址
    private static bool IsProxyIpAddress(IPAddress ipAddress)
    {
        byte[] addressBytes = ipAddress.GetAddressBytes();
        if (addressBytes[0] == 100 ||
            addressBytes[0] == 127 ||
            (addressBytes[0] == 169 && addressBytes[1] == 254) ||
            (addressBytes[0] == 172 && addressBytes[1] == 16) ||
            (addressBytes[0] == 192 && addressBytes[1] == 0 && addressBytes[2] == 2))
        {
            return true;
        }
        return false;
    }

    /// <summary>
    /// 获取局域网电脑 MAC地址
    /// </summary>
    /// <param name="separator"></param>
    /// <returns></returns>
    public static List<string> GetActiveMacAddress(string separator = "-")
    {
        //本地计算机网络连接信息
        IPGlobalProperties computerProperties = IPGlobalProperties.GetIPGlobalProperties();
        //获取本机电脑名
        var HostName = computerProperties.HostName;
        //获取域名
        var DomainName = computerProperties.DomainName;
        //获取本机所有网络连接
        NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();

        var macAddress = new List<string>();
        if (nics == null || nics.Length < 1)
        {
            //Debug.WriteLine("  No network interfaces found.");
            return macAddress;
        }

        //Debug.WriteLine("  Number of interfaces .................... : {0}", nics.Length);
        foreach (NetworkInterface adapter in nics.Where(c =>
            c.NetworkInterfaceType != NetworkInterfaceType.Loopback && c.OperationalStatus == OperationalStatus.Up))
        {
            IPInterfaceProperties properties = adapter.GetIPProperties();

            var unicastAddresses = properties.UnicastAddresses;
            if (unicastAddresses.Any(temp => temp.Address.AddressFamily == AddressFamily.InterNetwork))
            {
                var address = adapter.GetPhysicalAddress();

                if (string.IsNullOrEmpty(separator))
                {
                    macAddress.Add(address.ToString());
                }
                else
                {
                    var MACIp = "";
                    byte[] bytes = address.GetAddressBytes();
                    for (int i = 0; i < bytes.Length; i++)
                    {
                        MACIp += bytes[i].ToString("X2");

                        if (i != bytes.Length - 1)
                        {
                            MACIp += separator;
                        }
                    }

                    macAddress.Add(MACIp);
                }
            }
        }
        return macAddress;
    }
}
